//! @author Adam Emil Skoog
//! @date   2011-12-24

#include "EventManager.h"
#include "MouseInputEventReceiver.h"
#include "KeyInputEventReceiver.h"
#include <cassert>

namespace kedja
 {
	/**
	 * Constructor.
	 */
	EventManager::EventManager()
	 {
		// Initialise the values.
		for (unsigned i(0); i < static_cast<unsigned>(mouse::count); ++ i)
			mouseButtonDown[i]          =
			mouseButtonDownLastFrame[i] = false;

		for (unsigned i(0); i < static_cast<unsigned>(sf::Key::Count); ++ i)
			keyDown[i]          =
			keyDownLastFrame[i] = false;
	 }

	/**
	 * Tells the event manager whether the specified mouse button
	 * is currently being held down. This should be done each frame,
	 * no matter the state. It should be done at the very beginning
	 * of each frame, before anything else is done.
	 *
	 * @param button The mouse button to inform about.
	 * @param down   Whether the specified mouse button is down.
	 */
	void EventManager::notifyMouseButtonIsDown(const mouse::Button &button,const bool &down)
	 {
		mouseButtonDown[static_cast<unsigned>(button)] = down;
	 }

	/**
	 * Returns whether the specified mouse button was pressed this frame.
	 *
	 * @param button The button to check.
	 * @return Whether the button was pressed this frame.
	 */
	bool EventManager::mouseButtonWasPressed(const mouse::Button &button) const
	 {
		return (mouseButtonDown[static_cast<unsigned>(button)] &&
				!mouseButtonDownLastFrame[static_cast<unsigned>(button)]);
	 }

	/**
	 * Returns whether the specified mouse button was released this frame.
	 *
	 * @param button The button to check.
	 * @return Whether the button was released this frame.
	 */
	bool EventManager::mouseButtonWasReleased(const mouse::Button &button) const
	 {
		return (!mouseButtonDown[static_cast<unsigned>(button)] &&
				mouseButtonDownLastFrame[static_cast<unsigned>(button)]);
	 }

	/**
	 * Returns whether the specified mouse button is currently being held down.
	 *
	 * @param button The button to check.
	 * @return Whether the button is currently held down.
	 */
	bool EventManager::mouseButtonIsDown(const mouse::Button &button) const
	 {
		return mouseButtonDown[static_cast<unsigned>(button)];
	 }

	void EventManager::notifyKeyIsDown(const sf::Key::Code &button,const bool &down)
	 {
		keyDown[static_cast<unsigned>(button)] = down;
	 }

	bool EventManager::keyWasPressed(const sf::Key::Code &button) const
	 {
		return (keyDown[static_cast<unsigned>(button)] &&
				!keyDownLastFrame[static_cast<unsigned>(button)]);
	 }

	bool EventManager::keyWasReleased(const sf::Key::Code &button) const
	 {
		return (!keyDown[static_cast<unsigned>(button)] &&
				keyDownLastFrame[static_cast<unsigned>(button)]);
	 }

	bool EventManager::keyIsDown(const sf::Key::Code &button) const
	 {
		return keyDown[static_cast<unsigned>(button)];
	 }

	/**
	 * This should be called at the beginning of each frame, and is done automatically
	 * by the main component, and thus is private.
	 */
	void EventManager::beginFrame()
	 {
		// Make sure that the mouse input event receiver class has been initialised.
		assert(static_cast<bool>(MouseInputEventReceiver::mouseInputEventReceivers));

		if (MouseInputEventReceiver::mouseInputEventReceivers)
		 {
			// Check for mouse input.
			for (unsigned i(0); i < static_cast<unsigned>(mouse::count); ++ i)
			 {
				if (mouseButtonWasPressed(static_cast<mouse::Button>(i)))
					for (unsigned j(0); j < MouseInputEventReceiver::getMouseInputEventReceiverCount(); ++ j)
						if (MouseInputEventReceiver::getMouseInputEventReceiver(j)->onMouseButtonPress)
							MouseInputEventReceiver::getMouseInputEventReceiver(j)->onMouseButtonPress(static_cast<mouse::Button>(i));

				if (mouseButtonWasReleased(static_cast<mouse::Button>(i)))
					for (unsigned j(0); j < MouseInputEventReceiver::getMouseInputEventReceiverCount(); ++ j)
						if (MouseInputEventReceiver::getMouseInputEventReceiver(j)->onMouseButtonRelease)
							MouseInputEventReceiver::getMouseInputEventReceiver(j)->onMouseButtonRelease(static_cast<mouse::Button>(i));
			 }

			for (unsigned i(0); i < static_cast<unsigned>(sf::Key::Count); ++ i)
			 {
				if (keyWasPressed(static_cast<sf::Key::Code>(static_cast<sf::Key::Code>(i))))
					for (unsigned j(0); j < KeyInputEventReceiver::getKeyInputEventReceiverCount(); ++ j)
						if (KeyInputEventReceiver::getKeyInputEventReceiver(j)->onKeyPress)
							KeyInputEventReceiver::getKeyInputEventReceiver(j)->onKeyPress(static_cast<sf::Key::Code>(i));

				if (keyWasReleased(static_cast<sf::Key::Code>(static_cast<sf::Key::Code>(i))))
					for (unsigned j(0); j < KeyInputEventReceiver::getKeyInputEventReceiverCount(); ++ j)
						if (KeyInputEventReceiver::getKeyInputEventReceiver(j)->onKeyRelease)
							KeyInputEventReceiver::getKeyInputEventReceiver(j)->onKeyRelease(static_cast<sf::Key::Code>(i));
			 }
		 }
	 }

	/**
	 * This should be called at the end of each frame, and is done automatically
	 * by the main component, and thus is private.
	 */
	void EventManager::endFrame()
	 {
		for (unsigned i(0); i < static_cast<unsigned>(mouse::count); ++ i)
			mouseButtonDownLastFrame[i] = mouseButtonDown[i];

		for (unsigned i(0); i < static_cast<unsigned>(sf::Key::Count); ++ i)
			keyDownLastFrame[i] = keyDown[i];
	 }
 }
